﻿#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <qdatetime.h>
#include <callback_funcs.h>
#include <grid_manager.h>
#include <levent.h>

//生成随机字符串
static QString getRandomString(int nLen)
{
  qsrand(QDateTime::currentMSecsSinceEpoch());
  const char ch[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  int size = sizeof(ch);
  char* str = new char[nLen + 1];
  int num = 0;
  for (int nIndex = 0; nIndex < nLen; ++nIndex)
  {
    num = rand() % (size - 1);
    str[nIndex] = ch[num];
  }
  str[nLen] = '\0';
  QString res(str);
  return res;
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //创建句柄
    m_handle = CreateYinshuInstance();
    //创建管理器
    _gridManager=new GridManager(ui->gridLayout_2,this,m_handle);
    //重置界面
    ResetUI();
    _nickName = "yinshu_desktop";

    //信令回调
    static SignalCallbacks signalCallbacks;
    signalCallbacks.OnPeerLeaved=OnPeerLeaved;
    signalCallbacks.OnRoomStoped=OnMeetingEnd;
    signalCallbacks.OnEnableScreenshare=OnEnableScreenshareCallback;
    //丢包率数据
    signalCallbacks.OnMediaLinkInfo=OnMediaLinkInfoFun;
    signalCallbacks.OnPeerAudioVolumne=OnPeerAudioVolumneFun;
    signalCallbacks.OnMediaBandWidthInfo=OnMediaBandWidthInfoFun;


    InitSDK(m_handle, this, OnJoined, OnDisConnected, OnNewMemberJoined,
        nullptr, OnMemberEnableVideo, OnMemberDisableVideo,
            OnMemberEnableScreenShare,OnMemberDisableScreenShare, OnMemberUnMuteAudio, OnMemberMuteAudio,
        OnRecvUserData, OnSessionError, OnDevicesChanged,&signalCallbacks);
    ui->comboLogLevel->setCurrentIndex(2);

    ui->avator_url->setText("http://someone.jpg");
    //获取摄像头列表
    GetVideoDevices(m_handle, GetVideoDevicesResult);
    //获取麦克风列表
    GetAudioDevices(m_handle,true,GetAudioDevicesResult);
    //获取扬声器列表
    GetAudioDevices(m_handle, false, GetAudioDevicesResult);


    UpdateUI();
    //默认自适应
    ui->comboNAP->setCurrentIndex(2);
    //隐藏屏幕共享窗口
    ui->screenWnd->setHidden(true);

    //注册事件过滤器
    this->installEventFilter(this);

    _dataModel=new QStandardItemModel(this);
    QStringList headers;
    headers << QString(u8"参会人Id") << QString(u8"链路名称") << QString(u8"媒体类别")
            << QString(u8"编码") << QString(u8"分辨率(宽)") << QString(u8"分辨率(高)")
            << QString(u8"音量/帧率")<< QString(u8"包数")
            << QString(u8"丢包数量")<< QString(u8"字节数量")<< QString(u8"丢包率 ")
            << QString(u8"媒体码率(Kbps)")<< QString(u8"延迟(毫秒)") ;
    _dataModel->setHorizontalHeaderLabels(headers);
    ui->linkStatus->setModel(_dataModel);
}
//设置初始化UI状态
void MainWindow::ResetUI(){
    ui->videoCtrlButton->setText(QString(u8"closevideo"));
    ui->audioCtrlButton->setText(QString(u8"closeaudio"));
    ui->screenShareBtn->setText(QString(u8"sharescreen"));
    ui->connectStatus->setText(QString(u8"连接断开"));
    _gridManager->reset();
    ui->screenWnd->setHidden(true);
}
//处理用户离开
void MainWindow::ProcessPeerLeave(std::string peerId){
    // 获取模型
    QStandardItemModel *model = qobject_cast<QStandardItemModel*>(ui->linkStatus->model());
    QList<QPersistentModelIndex> toRemove;
    for (int i = 0; i < model->rowCount(); ++i) {
        QString peerName = model->index(i, 0).data().toString();
        if (peerName.toStdString() == peerId) {
            toRemove.push_back(model->index(i, 0));
        }
    }
    if(toRemove.size()>0)
        model->removeRows(toRemove.first().row(), toRemove.size());
}
void MainWindow::UpdateUI(){
    _roomid = ui->roomIds->currentText().toStdString();
    _dispServer=ui->dispatchComb->currentText().toStdString();
    _roomPasswd=ui->room_passwd->text().toStdString();
    if(_roomid=="92916"){
        _roomPasswd="556595";
    }else if(_roomid=="50071"){
    #if defined(DEBUG) || defined(_DEBUG)
        _roomPasswd="1111111";
    #else
        _roomPasswd="2222222";
    #endif
    }
    ui->room_passwd->setText(QString(_roomPasswd.c_str()));
    //头像url
    avator_url=ui->avator_url->displayText().toStdString();
}
//设置窗口可见
void MainWindow::SetWidgetVisible(QWidget *w,bool visible){
    //事件参数
    QVariant msgData;
    msgData.setValue(std::pair<QWidget *,bool>(w,visible));
    QPostMessage(this,999,msgData);
}

MainWindow::~MainWindow()
{
    delete ui;
}

bool MainWindow::eventFilter(QObject *obj, QEvent *event){
    if (event->type() == LEvent::m_eventType) {
        LEvent* e=(LEvent*)event;
        //隐藏视频窗口
        if(e->m_message==999){
            QWidget *w=e->m_params.value<std::pair<QWidget *,bool>>().first;
            bool visible=e->m_params.value<std::pair<QWidget *,bool>>().second;
            w->setHidden(!visible);
        }else if(e->m_message==888){
            nlohmann::json jRet=e->m_params.value<nlohmann::json>();
            updateLinkStatus(jRet);
        }else if(e->m_message==890){
            nlohmann::json jRet=e->m_params.value<nlohmann::json>();
            //获取上下行带宽
            float upBandWidth=jRet["upBandWidth"].get<float>();
            float downBandWidth=jRet["downBandWidth"].get<float>();
            ui->upBandWidth->setText(QString::number(upBandWidth,'f',2));
            ui->downBandWidth->setText(QString::number(downBandWidth,'f',2));
        }else if(e->m_message==777){
            //会议结束，恢复界面
            this->ResetUI();
        }else if(e->m_message==666){
            //成功加入
            ui->connectStatus->setText(QString(u8"入会成功"));
        }
        return true;
    }
    // standard event processing
    return QObject::eventFilter(obj, event);
}

//重写
void MainWindow::mouseDoubleClickEvent(QMouseEvent* event)
{
}
//覆写closeEvent函数
void MainWindow::closeEvent(QCloseEvent *){
    //直接退出
    ReleaseSdk(m_handle);
    DestoryYinshuInstance();
}
//加入房间
void MainWindow::on_Join_clicked()
{
    UpdateUI();
    ResetUI();
    //重新获取用户ID
    _memberId=ui->memberId->text().toStdString();
    if(_memberId==""){
        _memberId = getRandomString(8).toStdString();
        ui->memberId->setText(QString(_memberId.c_str()));
    }

    std::string mediaType=ui->mediaType->currentText().toStdString();
    bool bSimulcast=ui->cbSimulcast->isChecked();

    //设置分辨率和帧率
    QString res = ui->comboResolution->currentText();
    QStringList lst = res.split("x");
    int w = lst[0].toInt();
    int h = lst[1].toInt();
    int pol = ui->comboNAP->currentIndex();
    SetVideoSize(m_handle, w, h);

    //设置本地
    VideoWidget* video=_gridManager->getGridForPeer(_memberId);
    video->setPeerId(_memberId);
    video->setHasVideo(true);
    SetRenderWindow(m_handle, _memberId.c_str(), (void*)video->winId(), false);

    const char* jsonRet=NULL;
    if(mediaType=="AudioOnly"){
        jsonRet=JoinRoom(m_handle,_dispServer.c_str(), _roomid.c_str(),_roomPasswd.c_str(), MediaType::MediaType_Audio, _memberId.c_str(),
        _nickName.c_str(),avator_url.c_str());
    }else{
        jsonRet=JoinRoom(m_handle,_dispServer.c_str(), _roomid.c_str(),_roomPasswd.c_str(), MediaType::MediaType_Video, _memberId.c_str(),
        _nickName.c_str(),avator_url.c_str(),bSimulcast);
    }    
}


void MainWindow::on_Join_2_clicked()
{
    if (!m_handle)
        return;
    LeaveRoom(m_handle);
    //重置界面
    ResetUI();
}


void MainWindow::on_comboMics_currentIndexChanged(int index)
{
    if(index<0)return;
    QString deviceName=ui->comboMics->currentText();
    int audioDeviceIdx=this->_micsMap[index];
    SetAudioDevice(m_handle,true, audioDeviceIdx);
}


void MainWindow::on_comboSpeakers_currentIndexChanged(int index)
{
    if(index<0)return;
    //改变扬声器
    QString deviceName=ui->comboSpeakers->currentText();
    int audioDeviceIdx=_speakersMap[index];
    SetAudioDevice(m_handle,false, index);
}

Q_DECLARE_METATYPE(nlohmann::json)
void MainWindow::on_comboCamera_currentIndexChanged(int index)
{
    if(index<0)return;
    //改变摄像头
    QString str=ui->comboCamera->currentText();
    int selectedIndex=_camerasMap[index];
    SetVideoDevice(m_handle,selectedIndex);
    const char* jsonStr=GetVideoDeviceJson(m_handle,selectedIndex);
    nlohmann::json jsonDevice=nlohmann::json::parse(jsonStr);
    ui->comboResolution->clear();
    for(auto& it:jsonDevice["resolutionList"]){
        QVariant variant;
        variant.setValue(it);
        std::string strResolution=std::to_string(it["width"].get<int>()) + "x" + std::to_string(it["height"].get<int>());
        ui->comboResolution->addItem(strResolution.c_str(),variant);
    }
}
void MainWindow::updateLinkStatus(const nlohmann::json linkInfos){
    // 获取模型
    QStandardItemModel *model = qobject_cast<QStandardItemModel*>(ui->linkStatus->model());
     // 遍历所有输入的linkInfo
    for (auto linkInfo : linkInfos) {
        // 查找是否已有相同的peerName和linkName
        std::string str=linkInfo.dump();
        int row = -1;
        for (int i = 0; i < model->rowCount(); ++i) {
            QString peerName = model->index(i, 0).data().toString();
            QString linkName = model->index(i, 1).data().toString();
            if (peerName.toStdString() == linkInfo["peerName"].get<std::string>() &&
                linkName.toStdString() == linkInfo["linkName"].get<std::string>()) {
                row = i;
                break;
            }
        }
        // 如果找到,更新内容,否则新增一行
        if (row == -1) {
            row = model->rowCount();
            model->insertRow(row);
        }
        // 更新每列的值
        model->setData(model->index(row, 0), linkInfo["peerName"].get<std::string>().c_str());
        model->setData(model->index(row, 1), linkInfo["linkName"].get<std::string>().c_str());
        model->setData(model->index(row, 2), linkInfo["isVideo"].get<bool>()?"视频":"音频");
        model->setData(model->index(row, 3), linkInfo["codecName"].get<std::string>().c_str());
        model->setData(model->index(row, 4), linkInfo["width"].get<int>());
        model->setData(model->index(row, 5), linkInfo["height"].get<int>());
        model->setData(model->index(row, 6), linkInfo["level_or_fps"].get<int>());
        model->setData(model->index(row, 7), linkInfo["packets"].get<int>());
        model->setData(model->index(row, 8), linkInfo["packetLoss"].get<int>());
        model->setData(model->index(row, 9), linkInfo["bytes"].get<int>());
        model->setData(model->index(row, 10), linkInfo["lossRate"].get<float>());
        model->setData(model->index(row, 11), linkInfo["bitRate"].get<float>());
        model->setData(model->index(row, 12), linkInfo["delayMs"].get<int>());
        // 调整表格大小
        ui->linkStatus->resizeColumnsToContents();
        ui->linkStatus->resizeRowsToContents();
    }
}

void MainWindow::on_loggerButton_clicked()
{
    bool remote=ui->remoteLoger->checkState()==Qt::CheckState::Checked;
    int level=ui->comboLogLevel->currentIndex();
    //设置日志
    SetLoggerLevel(m_handle,true,level);
}


void MainWindow::on_roomIds_currentIndexChanged(int index)
{
    UpdateUI();
}

void MainWindow::on_audioCtrlButton_clicked()
{
    QString audioCtrlTitle=ui->audioCtrlButton->text();
    if(audioCtrlTitle==QString("closeaudio")){
       DisableMemberAudio(m_handle,_memberId.c_str(),NULL);
       ui->audioCtrlButton->setText(QString("openaudio"));
    }else if(audioCtrlTitle==QString("openaudio")){
        EnableMemberAudio(m_handle,_memberId.c_str(),NULL);
        ui->audioCtrlButton->setText(QString("closeaudio"));
    }
}
void MainWindow::on_videoCtrlButton_clicked(bool checked)
{
    QString videoCtrlTitle=ui->videoCtrlButton->text();
//     videoCtrlTitle=QString("aa");
    if(videoCtrlTitle==QString("closevideo")){
       DisableMemberVideo(m_handle,_memberId.c_str(),NULL);
       ui->videoCtrlButton->setText(QString("openvideo"));
    }else if(videoCtrlTitle==QString("openvideo")){
       //设置分辨率和帧率
       QString res = ui->comboResolution->currentText();
       QStringList lst = res.split("x");
       int w = lst[0].toInt();
       int h = lst[1].toInt();
       int pol = ui->comboNAP->currentIndex();
       SetVideoSize(m_handle, w, h);

        EnableMemberVideo(m_handle,_memberId.c_str(),NULL);
        ui->videoCtrlButton->setText(QString("closevideo"));
    }
}
void MainWindow::on_screenShareBtn_clicked()
{
    QString scnShareTitle=ui->screenShareBtn->text();
    if(scnShareTitle==QString("sharescreen")){
       //停止屏幕共享
       EnableScreenShare(m_handle);
       ui->screenShareBtn->setText(QString("stopscreen"));
    }else if(scnShareTitle==QString("stopscreen")){
        DisableScreenShare(m_handle);
        ui->screenShareBtn->setText(QString("sharescreen"));
    }
}
//更改分辨率
void MainWindow::on_comboResolution_currentIndexChanged(int index)
{
    if(index<0)return;
    //设置分辨率和帧率
    QString res = ui->comboResolution->currentText();
    QStringList lst = res.split("x");
    int w = lst[0].toInt();
    int h = lst[1].toInt();
    int pol = ui->comboNAP->currentIndex();
    //带宽
    bool bSimulcast=ui->cbSimulcast->isChecked();
    int bps =CaclBandWidthNeeded(w,h,bSimulcast);
    bps *= 1.2;
    ui->byteRate->setText(QString(std::to_string(bps).c_str()));

    SetVideoSize(m_handle, w, h);
}
//设置网络敏感度
void MainWindow::on_networkSensitivity_currentIndexChanged(int index)
{
    std::string sensitivity=ui->networkSensitivity->currentText().toStdString();
    SetNetworkSensitivity(sensitivity.c_str());
}

//开始录制
void MainWindow::on_btnStartRecord_clicked()
{
    if(!m_handle)return;
    StartRecord(m_handle,"meeting.mp4");
}

//停止录制
void MainWindow::on_btnStopRecord_clicked()
{
    if(!m_handle)return;
    StopRecord(m_handle);
}


void MainWindow::on_btnLnkChk_clicked()
{
    static bool enableCheck=false;
    enableCheck = !enableCheck;
    // 获取模型
    QStandardItemModel *model = qobject_cast<QStandardItemModel*>(ui->linkStatus->model());
    for(int i=0;i<model->rowCount();i++){
        model->removeRow(i);
    }
    ui->btnLnkChk->setText(QString(enableCheck? QString("StopLinkCheck"):QString("LinkCheck")));
    EnableLinkCheck(m_handle,enableCheck,3000);
}




void MainWindow::on_btnFrame_clicked()
{
    //设置分辨率和帧率
    int fps = ui->editFramerate->text().toInt();
    SetFramerate(m_handle, fps);
}


void MainWindow::on_comboNAP_currentIndexChanged(int index)
{
    std::string strPolicy=ui->comboNAP->currentText().toStdString();

    NetAdaptPolicy policy= NAP_NO_ADAPTING;
    if(strPolicy=="NO_ADAPTING")policy=NAP_NO_ADAPTING;
    else if(strPolicy=="RESOLUTION_FIXED")policy=NAP_RESOLUTION_FIXED;
    else if(strPolicy=="RESOLUTION_DYNAMIC")policy=NAP_RESOLUTION_DYNAMIC;

    SetNetAdaptPolicy(m_handle,policy);
}


void MainWindow::on_btnBitrateSet_clicked()
{
    int bitrate=ui->byteRate->text().toInt();
    SetBitrate(m_handle,bitrate);
}

